﻿package{
	import flash.utils.*
	public class erlang{
		static function atom(str:String):ByteArray{
			var byte:ByteArray = new ByteArray();
			byte.writeByte(100);
			byte.writeShort(str.length);
			byte.writeMultiByte(str,"us-ascii");
			return byte;
		}
		static function string(data:String):ByteArray{
			var byte:ByteArray = new ByteArray();
			byte.writeByte(107);
			byte.writeShort(data.length);
			byte.writeUTFBytes(data);
			return byte;
		}
		static function tuple(arr:Array):ByteArray{
			var byte:ByteArray = new ByteArray();
			byte.writeByte(104);
			byte.writeByte(arr.length);
			for(var i:int = 0;i < arr.length;i++){
				byte.writeBytes(arr[i]);
			}
			return byte;
		}
		static function list(arr:Array):ByteArray{
			var byte:ByteArray = new ByteArray();
			byte.writeByte(108);
			byte.writeUnsignedInt(arr.length);
			for(var i:int = 0;i < arr.length;i++){
				byte.writeBytes(encode(arr[i]));
			}
			return byte;
		}
		static function binary(data:ByteArray):ByteArray{
			var byte:ByteArray = new ByteArray();
			byte.writeByte(109);
			byte.writeUnsignedInt(data.length);
			byte.writeBytes(data);
			return byte;
		}
		static function integer(data){
			var byte:ByteArray = new ByteArray();
			if(data >= 0 && data <= 255){
				byte.writeByte(97);
				byte.writeByte(data);
			}else{
				byte.writeByte(98);
				byte.writeInt(data);
			}
			return byte;
		}
		static function head(data:ByteArray):ByteArray{
			var byte:ByteArray = new ByteArray();
			byte.writeByte(131);
			byte.writeBytes(data);
			return byte;
		}
		static function decode2(data:ByteArray){
			data.position = 0;
			var b:int = data.readUnsignedByte();
			var len:int,num:int,i:int,now:ByteArray;
			var top:Array = [];
			if(b != 131)return {}
			b = data.readUnsignedByte();
			if(b != 104)return {}
			num = data.readUnsignedByte();
			for(i = 0;i < num;i++){
				b = data.readUnsignedByte();
				//atom,string
				if(b == 100 || b == 107){
					len = data.readUnsignedShort();
					now = new ByteArray();
					data.readBytes(now,0,len);
					top.push(now.toString());
				//binary
				}else if(b == 109){
					len = data.readUnsignedInt();
					now = new ByteArray();
					data.readBytes(now,0,len);
					top.push(now);
				//tuple
				}else if(b == 104){
					len = data.readUnsignedByte();
					now = new ByteArray();
					data.readBytes(now,0,len);
					
				//integer 32
				}else if(b == 98){
					top.push(data.readInt());
				//integer 8
				}else if(b == 97){
					top.push(data.readUnsignedByte());
				}
				
			}
			data.position = 0;
			return top;
		}
		static function decode(data:ByteArray){
			data.position = 0;
			var b:int = data.readUnsignedByte();
			if(b != 131)return {}
			return parse(data);
		}
		private static function parse(data:ByteArray){
			var b:int = data.readUnsignedByte();
			var len:int,now:ByteArray;

				//atom,string
				if(b == 100 || b == 107){
					len = data.readUnsignedShort();
					now = new ByteArray();
					data.readBytes(now,0,len);
					return now.toString();
				//tuple || list
				}else if(b == 104 || b == 108){
					len = b == 104 ? data.readUnsignedByte() : data.readUnsignedInt();
					var stack:Array = []
					for(var i:int = 0;i < len;i++){
						stack.push(parse(data));
					}
					if(b == 108)data.readByte();
					return stack;
				//binary
				}else if(b == 109){
					len = data.readUnsignedInt();
					now = new ByteArray();
					data.readBytes(now,0,len);
					return now;
				//integer 32
				}else if(b == 98){
					return data.readInt();
				//integer 8
				}else if(b == 97){
					return data.readUnsignedByte();
				}
		}
		static function encode(data){
			if(data is String){
				return string(data);
			}else if(data is int){
				return integer(data);
				
			}else if(data is Array){
				return list(data);
			}else if(data is ByteArray){
				return binary(data);
			}
		}
	}
}